{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 出力層の設計\n",
    "\n",
    "* ニューラルネットワークは分類問題と回帰問題の両方に用いることができる\n",
    "    * 分類問題\n",
    "        * 分類など\n",
    "        * 例\n",
    "            * グラフ上にプロットしたデータをズバッと二つに線で分ける\n",
    "            * 応用例としてはスパムメールフィルタ\n",
    "                * スパムか、スパムでは無いか\n",
    "        * 使う<font color=\"red\">出力層の</font>活性化関数\n",
    "            * <font color=\"red\">ソフトマックス関数</font>\n",
    "    * 回帰問題\n",
    "        * 予想など\n",
    "        * 例\n",
    "            * データ群から線を求める\n",
    "            * 株価の予想とか明日の天気の予想など\n",
    "        * 使う出力層の活性化関数\n",
    "            * 恒等関数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### 恒等関数とソフトマックス関数\n",
    "\n",
    "* 恒等関数\n",
    "    * 入力をそのまま出力する\n",
    "    * 入ってきたものに対して何も手を加えずに出力する関数\n",
    "* ソフトマックス関数\n",
    "    * $ \\displaystyle y_k=\\frac{\\exp(a_k)}{\\sum_{i=1}^{n} \\exp(a_i)} $\n",
    "    * 出力層が全部で $n$ 個あるとする\n",
    "    * $k$ 番目の出力は $y_k$\n",
    "    * $a_k$ は入力信号\n",
    "    * 分母は全ての入力信号の指数関数の和\n",
    "        * 出力の各ニューロンが全ての入力信号の影響を受ける\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.01821127  0.24519181  0.73659691]\n"
     ]
    }
   ],
   "source": [
    "import numpy  as np\n",
    "\n",
    "a = np.array([0.3, 2.9, 4.0])\n",
    "exp_a = np.exp(a)\n",
    "# print(exp_a)\n",
    "\n",
    "sum_exp_a = np.sum(exp_a)\n",
    "#print(sum_exp_a)\n",
    "\n",
    "y = exp_a / sum_exp_a\n",
    "#print(y)\n",
    "\n",
    "### 関数として定義\n",
    "def softmax(a):\n",
    "    exp_a = np.exp(a)\n",
    "    sum_exp_a = np.sum(exp_a)\n",
    "    y = exp_a / sum_exp_a\n",
    "    \n",
    "    return y\n",
    "\n",
    "print(softmax(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### ソフトマックス関数の実装上の注意\n",
    "\n",
    "* オーバーフローに関する問題\n",
    "    * オーバーフロー\n",
    "        * 数には有効桁数が有り、とても大きな値は表現できない\n",
    "            * 表現できる数値の範囲に限界がある\n",
    "    * 指数関数の値が大きくなるとオーバーフローする\n",
    "        * そのような大きな値同士で割り算を行うと数値が不安定な結果になってしまう\n",
    "        \n",
    "### ソフトマックス関数の実装改善\n",
    "\n",
    "\\begin{align*}\n",
    "y_k &= \\frac{\\exp(a_k)}{\\sum_{i=1}^{n} \\exp(a_i)} \\\\\n",
    "&= \\frac{C \\exp(a_k)}{C \\sum_{i=1}^{n} \\exp(a_i)} \\\\\n",
    "&= \\frac{\\exp(a_k + \\log C) }{\\sum_{i=1}^{n} \\exp(a_i + \\log C)} \\\\\n",
    "&= \\frac{\\exp(a_k + C') }{\\sum_{i=1}^{n} \\exp(a_i + C')}\n",
    "\\end{align*}\n",
    "\n",
    "* $C$ という任意の定数を分母と分子にかけて指数関数の中に移動させて $C'$としている\n",
    "    * <font color=\"red\">分母と分子に同じ定数をかけているだけなので元の式は変更されていない</font>\n",
    "    * $C'$ はどのような値を用いることもできるが、オーバーフロー対策としては入力信号の中で最大の値を用いる事が一般的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ nan  nan  nan]\n",
      "[  0 -10 -20]\n",
      "[  9.99954600e-01   4.53978686e-05   2.06106005e-09]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/pyenv/versions/3.6.1/envs/jupyter/lib/python3.6/site-packages/ipykernel/__main__.py:4: RuntimeWarning: overflow encountered in exp\n",
      "/usr/local/pyenv/versions/3.6.1/envs/jupyter/lib/python3.6/site-packages/ipykernel/__main__.py:4: RuntimeWarning: invalid value encountered in true_divide\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1010, 1000, 990])\n",
    "\n",
    "### オーバーフローする\n",
    "print(np.exp(a) / np.sum(np.exp(a)))\n",
    "\n",
    "c = np.max(a)\n",
    "print(a - c)\n",
    "\n",
    "print(np.exp(a-c) / np.sum(np.exp(a-c)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  9.99954296e-01   4.53978548e-05   3.05888340e-07]\n",
      "[  0 -10 -15]\n",
      "[  9.99954296e-01   4.53978548e-05   3.05888340e-07]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([20, 10, 5])\n",
    "print(np.exp(a) / np.sum(np.exp(a)))\n",
    "\n",
    "c = np.max(a)\n",
    "print(a - c)\n",
    "\n",
    "print(np.exp(a-c) / np.sum(np.exp(a-c)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### ソフトマックス関数の再実装"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.01821127  0.24519181  0.73659691]\n",
      "1.0\n"
     ]
    }
   ],
   "source": [
    "import numpy  as np\n",
    "\n",
    "a = np.array([0.3, 2.9, 4.0])\n",
    "exp_a = np.exp(a)\n",
    "\n",
    "def softmax(a):\n",
    "    c = np.max(a)\n",
    "    exp_a = np.exp(a-c)\n",
    "    sum_exp_a = np.sum(exp_a)\n",
    "    y = exp_a / sum_exp_a\n",
    "    \n",
    "    return y\n",
    "\n",
    "y = softmax(a)\n",
    "print(y)\n",
    "print(np.sum(y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### ソフトマックス関数の特徴\n",
    "\n",
    "* 出力\n",
    "    * 0〜1.0の間の実数になる\n",
    "* 総和\n",
    "    * 1になる\n",
    "        * つまり、<font color=\"red\">ソフトマックス関数の出力を「確率」として解釈できる</font>\n",
    "        * y[0] = 1.8%, y[1] = 24.5%, y[2] = 73.7%,\n",
    "            * y[2]がもっとも確率が高いため、答えは2番目のクラスという答え方ができる\n",
    "            * それぞれの確率で各クラスになりえる、という確率的な答え方もできる\n",
    "* ソフトマックス関数を適用しても各要素の大小関係は変わらない\n",
    "    * 指数関数は単調増加関数であるため\n",
    "    * ニューラルネットワークのクラス分類は一般的に<font color=\"red\">出力の一番大きいニューロンに相当するクラスだけを認識結果とする</font>\n",
    "        * ソフトマックス関数を適用しても出力の一番大きいニューロンの位置は変わらない\n",
    "            * ニューラルネットワークによる分類では、出力層のソフトマックス関数は省略することができる\n",
    "            * 指数関数の計算はそれなりにコンピュータ計算が必要になるため、出力層のソフトマックス関数は省略すのが一般的\n",
    "    * 機械学習の「学習」と「推論」のフェーズにおいて、「推論」のフェーズではソフトマックス関数を省略するのが一般的\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 出力層のニューロンの数\n",
    "\n",
    "* クラス分類を行う問題\n",
    "    * 分類したいクラスの数に設定するのが一般的\n",
    "    * 例\n",
    "        * ある入力画像に対してそれが0〜９のどれかを予想する(10クラス分類問題)の場合、出力層のニューロンの数は10個に設定する"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 手書き数字認識\n",
    "\n",
    "* 機械学習の問題を解く手順\n",
    "    * 学習\n",
    "        * 訓練データ(学習データ)を使って重みパラメータの学習を行う\n",
    "    * 推論\n",
    "        * 先に学習したパラメータを使って入力データの分類を行う"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### MNISTデータセット\n",
    "\n",
    "* MNISTデータセット\n",
    "    * 手書き数字の画像セット\n",
    "    * 機械学習の分野で最も有名なデータセットの一つ\n",
    "    * 簡単な実験から論文として発表される研究まで様々な場所で利用される\n",
    "        * 実際に論文でも実験用のデータとしてよく登場する\n",
    "    * 訓練画像60000枚、テスト画像10000枚用意されている\n",
    "        * 28x28のグレー画像(1チャンネル)で各ピクセルは0〜255までの値を取る\n",
    "        * それぞれの画像データに対しては数値に対応するラベルが与えられている"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### PythonスクリプトによるMNISTデータセットの確認\n",
    "\n",
    "* mnist.py\n",
    "    * やること\n",
    "        * データセットのダウンロード\n",
    "        * 画像データのNumPy配列変換\n",
    "    * load_mnist関数\n",
    "        * 読み込み\n",
    "            * 1回目 : ネット上からMNISTデータをダウンロード\n",
    "            * 2回目以降 : ローカルに保存したpickleファイルを読み込む\n",
    "        * 返す値\n",
    "            * x_train : 訓練画像\n",
    "            * t_train : 訓練ラベル\n",
    "            * x_test : テスト画像\n",
    "            * t_test : テストラベル\n",
    "        * 引数\n",
    "            * normalize\n",
    "                * 入力画像を0.0〜1.0に正規化するかを選択\n",
    "                    * Falseだと入力画像のピクセルは0〜255のまま\n",
    "            * flatten\n",
    "                * 入力画像を平らにする(1次元配列にする)かどうかを設定\n",
    "                    * True : 784個の要素からなる1次元配列として格納される\n",
    "                    * False : 1 x 28 x 28の3次元配列として格納される\n",
    "            * one_hot_lavel\n",
    "                * ラベルをone_hotとして格納するかどうかを設定する\n",
    "                    * one_hotラベル\n",
    "                        * 正解となるラベルが1でそれ以外は0の配列\n",
    "                        * 例) [0,0,1,0,0,0,1,1,0] \n",
    "                * True : one_hot1ラベル\n",
    "                * False : 7 ,2　のように単純に正解のラベルが格納される"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['', '/usr/local/pyenv/versions/3.6.1/lib/python36.zip', '/usr/local/pyenv/versions/3.6.1/lib/python3.6', '/usr/local/pyenv/versions/3.6.1/lib/python3.6/lib-dynload', '/usr/local/pyenv/versions/jupyter/lib/python3.6/site-packages', '/usr/local/pyenv/versions/jupyter/lib/python3.6/site-packages/IPython/extensions', '/Users/ftakao2007/.ipython', '/Users/ftakao2007/work/jupyter/deep-learning-from-scratch']\n"
     ]
    }
   ],
   "source": [
    "import sys, os\n",
    "\n",
    "#sys_path = '/Users/ftakao2007/jupyter/deep-learning-from-scratch'\n",
    "#sys_path = '/root/jupyter/deep-learning-from-scratch'\n",
    "sys_path = os.environ['PYENV_DIR'] + \"/deep-learning-from-scratch\"\n",
    "if not sys_path in sys.path:\n",
    "    sys.path.append(sys_path)\n",
    "\n",
    "from dataset.mnist import load_mnist\n",
    "print(sys.path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(60000, 784)\n",
      "(60000,)\n",
      "(10000, 784)\n",
      "(10000,)\n"
     ]
    }
   ],
   "source": [
    "(x_train, t_train), (x_test, t_test) = \\\n",
    "    load_mnist(flatten=True, normalize=False)\n",
    "    \n",
    "#print(x_train)\n",
    "print(x_train.shape)\n",
    "print(t_train.shape)\n",
    "print(x_test.shape)\n",
    "print(t_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "(784,)\n",
      "(28, 28)\n"
     ]
    }
   ],
   "source": [
    "import sys, os\n",
    "#sys_path = '/Users/ftakao2007/jupyter/deep-learning-from-scratch'\n",
    "#sys_path = '/root/jupyter/deep-learning-from-scratch'\n",
    "sys_path = os.environ['PYENV_DIR'] + \"/deep-learning-from-scratch\"\n",
    "if not sys_path in sys.path:\n",
    "    sys.path.append(sys_path)\n",
    "\n",
    "import numpy as np\n",
    "from dataset.mnist import load_mnist\n",
    "from PIL import Image\n",
    "\n",
    "def img_show(img):\n",
    "    # PIL用オブジェクトに変換\n",
    "    pil_img = Image.fromarray(np.uint8(img))\n",
    "    pil_img.show()\n",
    "\n",
    "(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)\n",
    "\n",
    "img = x_train[0]\n",
    "label = t_train[0]\n",
    "print(label)  # 5\n",
    "\n",
    "print(img.shape)  # (784,)  入力画像を784個の要素からなる1次元配列に格納\n",
    "img = img.reshape(28, 28)  # 形状を元の画像サイズに変形\n",
    "print(img.shape)  # (28, 28)\n",
    "\n",
    "### 画像の表示(ローカル実行のみ)\n",
    "img_show(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "(784,)\n",
      "(28, 28)\n"
     ]
    }
   ],
   "source": [
    "img = x_train[1]\n",
    "label = t_train[1]\n",
    "print(label)  # 0\n",
    "\n",
    "print(img.shape)  # (784,)\n",
    "img = img.reshape(28, 28)  # 形状を元の画像サイズに変形\n",
    "print(img.shape)  # (28, 28)\n",
    "\n",
    "### 画像の表示(ローカル実行のみ)\n",
    "img_show(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "(784,)\n",
      "(28, 28)\n"
     ]
    }
   ],
   "source": [
    "img = x_train[2]\n",
    "label = t_train[2]\n",
    "print(label)  # 4\n",
    "\n",
    "print(img.shape)  # (784,)\n",
    "img = img.reshape(28, 28)  # 形状を元の画像サイズに変形\n",
    "print(img.shape)  # (28, 28)\n",
    "\n",
    "### 画像の保存\n",
    "Image.fromarray(np.uint8(img)).save('img/text_img_numpy.jpg', 'JPEG', quality=100, optimize=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "画像の表示\n",
    "\n",
    "<img src=\"img/text_img_numpy.jpg\" alt=\"numpy画像の保存\" title=\"numpy画像の保存\" align=\"left\" />  \n",
    "\n",
    "<br clear=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### ニューラルネットワークの推論処理\n",
    "\n",
    "* 推論処理を行うニューラルネットワークを実装\n",
    "    * 入力層\n",
    "        * 784個のニューロン\n",
    "            * 画像サイズ 28 x 28 = 784から\n",
    "    * 出力層\n",
    "        * 10個のニューロン\n",
    "            * 10クラス分類(0〜9の数字)\n",
    "    * 隠れ層1\n",
    "        * 50個のニューロン\n",
    "        * 任意の値\n",
    "    * 隠れ層2\n",
    "        * 100個のニューロン\n",
    "        * 任意の値\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "def get_data():\n",
    "    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)\n",
    "    return x_test, t_test\n",
    "\n",
    "# 学習済みの重みパラメータ(重みとバイアスのパラメータがディクショナリ型の変数として保存されている)\n",
    "#pkl = \"/root/jupyter/deep-learning-from-scratch/ch03/sample_weight.pkl\"\n",
    "#pkl = \"/Users/ftakao2007/jupyter/deep-learning-from-scratch/ch03/sample_weight.pkl\"\n",
    "pkl= os.environ['PYENV_DIR'] + \"/deep-learning-from-scratch/ch03/sample_weight.pkl\"\n",
    "\n",
    "# 学習済み重みパラメータの読み込み\n",
    "def init_network():\n",
    "    with open(pkl, \"rb\") as f:\n",
    "        network = pickle.load(f)\n",
    "        \n",
    "    return network\n",
    "\n",
    "def sigmoid(x):\n",
    "    return 1/(1 + np.exp(-x))\n",
    "\n",
    "def softmax(a):\n",
    "    c = np.max(a)\n",
    "    exp_a = np.exp(a-c)\n",
    "    sum_exp_a = np.sum(exp_a)\n",
    "    y = exp_a / sum_exp_a\n",
    "    \n",
    "    return y\n",
    "\n",
    "def predict(network, x):\n",
    "    W1, W2, W3 = network['W1'], network['W2'], network['W3']\n",
    "    b1, b2, b3 = network['b1'], network['b2'], network['b3']\n",
    "    \n",
    "    a1 = np.dot(x, W1) + b1\n",
    "    z1 = sigmoid(a1)\n",
    "    a2 = np.dot(z1, W2) + b2\n",
    "    z2 = sigmoid(a2)\n",
    "    a3 = np.dot(z2, W3) + b3\n",
    "    y = softmax(a3)\n",
    "    \n",
    "    return y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### ニューラルネットワークによる推論処理\n",
    "\n",
    "* 認識精度の評価\n",
    "    * どれだけ正しく分類手できているか\n",
    "* predict()関数の出力\n",
    "    * 各ラベルの確率がNumPy配列として出力される\n",
    "    * 例\n",
    "        * [0.1, 0.3, 0.05, 0.08, 0.1, 0.02, 0.1, 0.05, 0.1, 0.1]\n",
    "        * index i は数値iが出現する確率\n",
    "            * index 0は数値の0, index 9は数値の9\n",
    "            * index 1(数値の1)の出現確率が一番高い(0.3 = 30%)\n",
    "* 認識精度\n",
    "    * 学習済みニューラルネットワークを動かした段階で0.9352\n",
    "        * ニューラルネットワークの構造や学習方法を工夫すると99%を超える精度に行き着く"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from functools import reduce\n",
    "a = [0.1, 0.3, 0.05, 0.08, 0.1, 0.02, 0.1, 0.05, 0.1, 0.1]\n",
    "reduce(lambda x ,y : x + y, a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy:0.9352\n"
     ]
    }
   ],
   "source": [
    "import pickle\n",
    "\n",
    "# MNISTのデータセットを取得\n",
    "# xには画像データが入る\n",
    "x, t = get_data()\n",
    "\n",
    "# ネットワークを生成\n",
    "network = init_network()\n",
    "\n",
    "accuracy_cnt = 0\n",
    "for i in range(len(x)):\n",
    "    # 0〜9の数値それぞれの確率をリストで出す(画像データの分類を行う)\n",
    "    y = predict(network, x[i])\n",
    "    # 最大となる要素のindexを返す\n",
    "    p = np.argmax(y)\n",
    "    # 出力結果と実際のラベルの値を比較する\n",
    "    if p == t[i]:\n",
    "        # 出力結果とラベルが一致していれば+1する\n",
    "        accuracy_cnt += 1\n",
    "\n",
    "# 正答率を出力する\n",
    "print(\"Accuracy:\" + str(float(accuracy_cnt) / len(x)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### 正規化と前処理\n",
    "\n",
    "* 正規化(normalization)\n",
    "    * データをある決まった範囲に変換する処理\n",
    "        * 例 : load_mnist関数のnormalize引数をTrueにする\n",
    "            * 単純に画像のピクセル値を255で除算し、データが<font color=\"red\">0.0〜1.0の範囲に収まるように変換</font>\n",
    "    * 実践では\n",
    "        * データ全体の分布を考慮した正規化を行うことがよくある\n",
    "            * データ全体の平均や標準偏差を利用して、データ全体が0を中心に分布するように移動させる\n",
    "            * データの広がりをある範囲に収める\n",
    "            * データ全体の分布の形状を均一にする。これは白色化(whitening)と呼ばれる\n",
    "* 前処理(pre-processing)\n",
    "    * ニューラルネットワークの入力データに対して、何らかの決まった変換を行う事\n",
    "    * 実践的によく用いられる\n",
    "    * 有効性\n",
    "        * 識別性能の向上\n",
    "        * 学習の高速化\n",
    "* ここの推論処理の例の場合\n",
    "    * 「入力画像データに前処理として正規化」を行っている\n",
    "    * 単純に値を255で割る正規化"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### バッチ処理\n",
    "\n",
    "* バッチ(batch)\n",
    "    * まとまりのある入力データ\n",
    "* メリット\n",
    "    * 1枚あたりの計算時間を大幅に短縮できる\n",
    "        * 数値計算ライブラリの多くが大きな配列の計算を効率よく処理できるような最適化を行っているため\n",
    "        * データ転送がボトルネックになっている場合はバッチ処理を行うことでバス大域の負荷を軽減することができる\n",
    "            * 正確には、データの読み込みに対して演算の割合を多くすることができる\n",
    "        *　小さな配列を少しずつ計算するより大きな配列を一度に計算するほうが速い\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 784)\n",
      "(784,)\n",
      "(784, 50)\n",
      "(50, 100)\n",
      "(100, 10)\n",
      "(10000, 10)\n"
     ]
    }
   ],
   "source": [
    "import pickle\n",
    "x, t = get_data()\n",
    "network = init_network()\n",
    "W1, W2, W3 = network['W1'], network['W2'], network['W3']\n",
    "\n",
    "# バイアスは省略\n",
    "# 画像1000点、入力層の数784(28x28ピクセルの要素数)\n",
    "print(x.shape)\n",
    "\n",
    "# 一つ目の画像の入力\n",
    "print(x[0].shape)\n",
    "\n",
    "# 50個のニューロンがある隠れ層\n",
    "print(W1.shape)\n",
    "\n",
    "# 100個のニューロンがある隠れ層\n",
    "print(W2.shape)\n",
    "\n",
    "# 10個のニューロンがある出力層へ\n",
    "print(W3.shape)\n",
    "\n",
    "# 出力層\n",
    "b1, b2, b3 = network['b1'], network['b2'], network['b3']    \n",
    "a1 = np.dot(x, W1) + b1\n",
    "z1 = sigmoid(a1)\n",
    "a2 = np.dot(z1, W2) + b2\n",
    "z2 = sigmoid(a2)\n",
    "a3 = np.dot(z2, W3) + b3\n",
    "y = softmax(a3)\n",
    "print(y.shape)\n",
    "    "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
